﻿using System;
using System.Collections.Generic;
using System.Linq;
using System.Net;
using System.Windows;
using System.Windows.Controls;
using System.Windows.Documents;
using System.Windows.Input;
using System.Windows.Media;
using System.Windows.Media.Animation;
using System.Windows.Shapes;
using Microsoft.Phone.Controls;
using MReviewerClient.Helpers;
using MReviewerClient.Providers;
using System.ComponentModel;
using System.Threading;
using MReviewerClient.Models;
using MReviewerClient.MReviewerSvc;
using System.ServiceModel;

namespace MReviewerClient
{
    public partial class MainPage : PhoneApplicationPage
    {
        #region Fields

        /// <summary>
        /// The opacity of the Glass Rectangle
        /// </summary>
        private int OpacityValue;

        /// <summary>
        /// The OffSet for scale transformation
        /// </summary>
        private double OffSet;

        /// <summary>
        /// The decreasement offset which is used to scale transformation
        /// </summary>
        private const double DecreaseOffSet = -0.1;

        /// <summary>
        /// The increasement offset which is used to scale transformation
        /// </summary>
        private const double IncreaseOffSet = 0.1;

        /// <summary>
        /// This variable is used to mark the Glass animation has been changed
        /// </summary>
        private bool IsMakeAnimation = false;

        /// <summary>
        /// Refer to the selected button
        /// </summary>
        private Button SelectedButton = null;

        /// <summary>
        /// Show loading splash progress bar on a separate thread
        /// </summary>
        private BackgroundWorker backroungWorker;

        #endregion

        #region Constructors

        /// <summary>
        /// The default constructor
        /// </summary>
        public MainPage()
        {
            InitializeComponent();

            this.progressBar1.IsIndeterminate = true;
            // Hide the splash progress bar
            this.progressBar1.Visibility = System.Windows.Visibility.Collapsed;
            this.txtLoading.Visibility = System.Windows.Visibility.Collapsed;
        }

        #endregion

        #region Methods

        /// <summary>
        /// Try to connect to the service with the user input information
        /// </summary>
        private void TryConnectToService()
        {
            backroungWorker = new BackgroundWorker();
            backroungWorker.DoWork += new DoWorkEventHandler(backroungWorker_DoWork);
            backroungWorker.RunWorkerCompleted += new RunWorkerCompletedEventHandler(backroungWorker_RunWorkerCompleted);
            backroungWorker.RunWorkerAsync();
        }

        /// <summary>
        /// Handle worker executing
        /// </summary>
        /// <param name="sender"></param>
        /// <param name="e"></param>
        private void backroungWorker_DoWork(object sender, DoWorkEventArgs e)
        {
            // Display the splash progress bar
            this.Dispatcher.BeginInvoke(() =>
            {
                var errTxt = ServiceInfoProvider.Instance.ReadServiceInfo();
                if (errTxt.Equals(string.Empty))
                    EstablishmentModel.Instance.SelectAll();
            });
            Thread.Sleep(3000);
        }

        /// <summary>
        /// Handle worker execute completely
        /// </summary>
        /// <param name="sender"></param>
        /// <param name="e"></param>
        private void backroungWorker_RunWorkerCompleted(object sender, RunWorkerCompletedEventArgs e)
        {
            // Hide the splash progress bar
            this.Dispatcher.BeginInvoke(() =>
            {
                backroungWorker.DoWork -= new DoWorkEventHandler(backroungWorker_DoWork);
                backroungWorker.RunWorkerCompleted -= new RunWorkerCompletedEventHandler(backroungWorker_RunWorkerCompleted);

                this.progressBar1.Visibility = System.Windows.Visibility.Collapsed;
                this.txtLoading.Visibility = System.Windows.Visibility.Collapsed;

                // Navigate to the List All Establishment
                NavigationService.Navigate(new Uri("/Views/ListEstablishmentView.xaml", UriKind.Relative));
            });
        }

        private void btnListAllEstablishments_Click(object sender, RoutedEventArgs e)
        {
            if (this.IsMakeAnimation)
                return;
            this.SelectedButton = btnListAllEstablishments;
            this.ShowGlass();
        }

        private void btnRecordEstablishment_Click(object sender, RoutedEventArgs e)
        {
            this.SelectedButton = btnRecordEstablishment;
            this.ShowGlass();
        }

        private void btnConfiguration_Click(object sender, RoutedEventArgs e)
        {
            this.SelectedButton = btnConfiguration;
            this.ShowGlass();
        }

        private void btnAbout_Click(object sender, RoutedEventArgs e)
        {
            this.SelectedButton = btnAbout;
            this.ShowGlass();
        }

        /// <summary>
        /// Show the Glass Rectangle 
        /// </summary>
        /// <param name="btn"></param>
        private void ShowGlass()
        {
            if (this.SelectedButton == null)
                return;

            // Make animation
            this.OpacityValue = 1;
            this.OffSet = DecreaseOffSet;
            this.IsMakeAnimation = true;
            this.MakeAnimation();

            // Play click sound
            SoundProvider.Instance.PlaySound(@"Resources/click_09.wav");
        }

        /// <summary>
        /// Make animation for the Glass Rectangle
        /// </summary>
        /// <param name="rect"></param>
        private void MakeAnimation()
        {
            Rectangle rect = CommonProvider.Instance.GetTemplateChildByName(this.SelectedButton, "glassCube") as Rectangle;
            if (rect == null)
                return;

            // Show the Glass Rectangle 
            rect.Opacity = this.OpacityValue;

            // Make animation for the Button
            TransformGroup transformGroup = rect.RenderTransform as TransformGroup;
            ScaleTransform scaleTransform = transformGroup.Children[0] as ScaleTransform;

            // Scale X coordinate
            DoubleAnimation ScaleX = new DoubleAnimation();
            ScaleX.By = OffSet;
            ScaleX.Duration = TimeSpan.FromSeconds(0.5);

            Storyboard.SetTarget(ScaleX, scaleTransform);
            Storyboard.SetTargetProperty(ScaleX, new PropertyPath(ScaleTransform.ScaleXProperty));

            // Scale Y coordinate
            DoubleAnimation ScaleY = new DoubleAnimation();
            ScaleY.By = OffSet;
            ScaleY.Duration = TimeSpan.FromSeconds(0.5);

            Storyboard.SetTarget(ScaleY, scaleTransform);
            Storyboard.SetTargetProperty(ScaleY, new PropertyPath(ScaleTransform.ScaleYProperty));

            // Create storyboard, add animation, and fire it up! 
            Storyboard storyboard = new Storyboard();
            storyboard.Children.Add(ScaleX);
            storyboard.Children.Add(ScaleY);
            storyboard.Begin();

            // Navigation handler
            EventHandler navigationHandler = null;
            navigationHandler = (s, e) =>
            {
                if (!this.IsMakeAnimation)
                    return;

                switch (this.SelectedButton.Name)
                {
                    case "btnAbout":
                        NavigationService.Navigate(new Uri("/YourLastAboutDialog;component/AboutPage.xaml", UriKind.Relative));
                        break;

                    case "btnListAllEstablishments":
                        this.progressBar1.Visibility = System.Windows.Visibility.Visible;
                        this.txtLoading.Visibility = System.Windows.Visibility.Visible;
                        this.TryConnectToService();
                        break;

                    case "btnRecordEstablishment":
                        NavigationService.Navigate(new Uri("/Views/RecordEstablishmentView.xaml", UriKind.Relative));
                        break;
                        
                    case "btnConfiguration":
                        NavigationService.Navigate(new Uri("/Views/ConfigurationView.xaml", UriKind.Relative));
                        break;
                }
                storyboard.Completed -= navigationHandler;
            };
            storyboard.Completed += navigationHandler;
        }

        /// <summary>
        /// The callback method which is called when completed navigation in other pages
        /// </summary>
        /// <param name="e"></param>
        protected override void OnNavigatedFrom(System.Windows.Navigation.NavigationEventArgs e)
        {
            if (this.SelectedButton == null)
                return;

            // Restore Glass Rectangle to original
            this.OpacityValue = 0;
            this.OffSet = IncreaseOffSet;
            this.IsMakeAnimation = false;
            this.MakeAnimation();
        }

        private void PhoneApplicationPage_Loaded(object sender, RoutedEventArgs e)
        {
            // Read information of service
            this.ReadServiceInfo();
        }

        /// <summary>
        /// Read service information from resource file
        /// </summary>
        private void ReadServiceInfo()
        {
            var isValidConfig = true;

            if (ServiceInfoProvider.Instance.IsServiceInvalid)
            {
                // First read service information from saved file erlier
                var errTxt = ServiceInfoProvider.Instance.ReadServiceInfo();

                if (errTxt.NonEquals(string.Empty))
                    isValidConfig = false;
                else if (ServiceInfoProvider.Instance.IsServiceInvalid)
                    isValidConfig = false;

                if (isValidConfig == false)
                {
                    MessageBox.Show("Cannot read the service information", "Information", MessageBoxButton.OK);
                    // Navigate to the Configuration page
                    NavigationService.Navigate(new Uri("/Views/ConfigurationView.xaml", UriKind.Relative));
                    return;
                }
                else
                {
                    string ENDPOINT_ADDRESS_NAME = "BasicHttpBinding_ISvcMReviewer";
                    string DEFAULT_ENDPOINT_ADDRESS = "http://localhost:1383/SvcMReviewer.svc";

                    var serviceURL = string.Format("http://{0}:{1}/{2}", 
                        ServiceInfoProvider.Instance.ServiceName, ServiceInfoProvider.Instance.Port, ServiceInfoProvider.SERVICE_PATH);

                    try
                    {
                        // Try to connect the service
                        new MReviewerSvc.SvcMReviewerClient(ENDPOINT_ADDRESS_NAME,
                                        new EndpointAddress(serviceURL == string.Empty ? DEFAULT_ENDPOINT_ADDRESS : serviceURL));
                    }
                    catch
                    {
                        // Reset service information
                        ServiceInfoProvider.Instance.ServiceName = null;
                        ServiceInfoProvider.Instance.Port = null;
                        // Inform message to user
                        MessageBox.Show("The service information is invalid", "Information", MessageBoxButton.OK);
                        // Navigate to the Configuration page
                        NavigationService.Navigate(new Uri("/Views/ConfigurationView.xaml", UriKind.Relative));
                        return;
                    }
                }
            }

            // Select some models from the service
            if (MealTypeModel.Instance.MealTypes == null)
                MealTypeModel.Instance.SelectAll();

            if (EstablishmentTypeModel.Instance.EstablishmentTypes == null)
                EstablishmentTypeModel.Instance.SelectAll();

            if (FoodTypeModel.Instance.FoodTypes == null)
                FoodTypeModel.Instance.SelectAll();
        }

        #endregion        
    }
}